package org.beetl.json.node;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.beetl.json.ActionComparator;
import org.beetl.json.ActionReturn;
import org.beetl.json.JsonTool;
import org.beetl.json.JsonWriter;
import org.beetl.json.Location;
import org.beetl.json.OutputNode;
import org.beetl.json.action.IClassAction;
import org.beetl.json.action.ICycleAction;
import org.beetl.json.loc.ClassLocation;
import org.beetl.json.util.JsonUtil;

public class PojoNode implements OutputNode {

	Class c;
	List<PojoAttributeNode> attrs = new ArrayList<PojoAttributeNode>();
	boolean cycleCheck = false;
	ICycleAction cycleAction = null;
	
	public PojoNode(Class c) {
		this.c = c;
	}

	@Override
	public void render(Object obj, JsonWriter w) throws IOException {

		if(cycleCheck){
			if(w.containObject(obj)){
				this.cycleAction.cycleRender(this, obj, w);
				return ;
			}
			w.addObject(null, obj);
		}
		
		w.writeScopeChar('{');
		Iterator<PojoAttributeNode> it = attrs.iterator();
		if(!it.hasNext()){
			w.writeScopeChar('}');
			
		}else{
			while(true){
				PojoAttributeNode node = it.next();
				node.render(obj, w);
				if(!it.hasNext()){
					w.writeScopeChar('}');
					break;
				}else{
					w.writeComma();
				}
			
			}
		}
		
		if(this.cycleCheck){
			w.removeLast();
		}
	
		
	

	}

	@Override
	public void setActionByLocation(List<Location> list) {
		Method[] ms = c.getMethods();
		for (Method m : ms) {
			if (JsonUtil.isGetterMethod(m)) {
				// @todo: list map,class,etc node
				if (!JsonTool.isStopParse(m.getDeclaringClass().getName())) {
					PojoAttributeNode node = new PojoAttributeNode(c,m);	
					node.setActionByLocation(list);
					attrs.add(node);

				}

			}
		}

		{
			// 查找是否有作用到class的Action
			List<IClassAction> classActions = new ArrayList<IClassAction>(	);
			for (Location loc : list) {
				if (loc instanceof ClassLocation) {
					classActions.add((IClassAction) loc.getAction());
				}
			}
			
			Collections.sort(classActions,new ActionComparator());
			// 预先处理
			if (classActions.size() != 0) {
				for (IClassAction ca : classActions) {
					ActionReturn ar = ca.doit(this);
					if (ar.process) {
						attrs = (List<PojoAttributeNode>) ar.value;
					} else {
						break;
					}

				}

			}
		}

	}

	public List<PojoAttributeNode> getAttrs() {
		return attrs;
	}

	public boolean isCycleCheck() {
		return cycleCheck;
	}

	public void setCycleCheck(boolean cycleCheck) {
		this.cycleCheck = cycleCheck;
	}

	public ICycleAction getCycleAction() {
		return cycleAction;
	}

	public void setCycleAction(ICycleAction cycleAction) {
		this.cycleAction = cycleAction;
	}

}
